#!/usr/bin/python3

# Switch to a backend that doesn't need X
import matplotlib
from math import isclose
#matplotlib.use("Agg")

# Switch to a font with Unicode characters
from matplotlib import rcParams
#rcParams['font.sans-serif'] = ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif']
#rcParams['font.serif'] = ['DejaVu Serif', 'Bitstream Vera Serif', 'Computer Modern Roman', 'New Century Schoolbook', 'Century Schoolbook L', 'Utopia', 'ITC Bookman', 'Bookman', 'Nimbus Roman No9 L', 'Times New Roman', 'Times', 'Palatino', 'Charter', 'serif']

import matplotlib.backends.backend_pdf
import sys
import os
import matplotlib.pyplot as plt
import numpy
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
                               AutoMinorLocator)
from matplotlib.ticker import MaxNLocator
import pandas as pd


def plotUtilQuad(coreCount, expected_score, slope, distro, numPeriods, fileName):
    plt.rcParams['figure.figsize'] = [12, 12]
    fig = plt.figure()
    fig.tight_layout(rect=[0, 0.03, 1, 0.90])
    fig.tight_layout(True)
    #plt.rcParams['figure.figsize'] = [12, 9]
    for i in range(1, 5):
        #etc = fig.add_subplot(2,2,i)
        taskUtilRange=TASK_UTIL_RANGES[i-1]
        #print("Calling add_plot.")
        etc = fig.add_subplot(2,2,i)
        add_plot(etc, coreCount, expected_score, slope, distro, taskUtilRange, numPeriods)
        #test = add_plot(etc, coreCount, expected_score, slope, distro, taskUtilRange, numPeriods)
        # if we don't have the scenario, quit
        #if test == False:
        #    return 0
    if coreCount > 2:
        #plt.show()
        plt.savefig(FOLDER_OUT + fileName + ".pdf")
    plt.clf()
    fig.clf()

#edited
#Called by plot_util_quad_from_file
def setup_figure(fig, header, coreCount):
    #fig.legend(["Baseline","CERT-MT"])
    fig.set_ylim(0,1.02)
    fig.set_xlim(coreCount/2, 2*coreCount)
    fig.set_xlabel('Utilization')
    fig.set_ylabel('Schedulability Ratio')
    fig.set_title(header)


#called by plot_util_quad_from_file
def add_plot(target, coreCount, expected_score, slope, distro, taskUtilRange, numPeriods):
    
    #add x-axis tick marks to graph
    minTotalUtil=int(.75*coreCount)
    maxTotalUtil=int(coreCount*2)
    ticks=[]
    for j in range(minTotalUtil, maxTotalUtil+1):
        ticks.append(j)
    target.set_xticks(ticks)
    
    #what are the utilization points we need to plot?
    util=[]
    j=0
    while j * BIN_SIZE <= maxTotalUtil:
        util.append(coreCount/2+j*BIN_SIZE-BIN_SIZE)
        j+=1
        

    scenarioAllModels=df[(df['coreCount'] == coreCount) &
        (df['minTaskUtil'] == taskUtilRange[0]) &
        (df['maxTaskUtil'] == taskUtilRange[1]) &
        (df['numPeriods'] == numPeriods) &
        (df['expected_score'] == expected_score) &
        (df['score_distro'] == distro) &
        (df['slope'] == slope) &
        (df['bestPartition'] == True) ]

    # nothing to do if we don't have this scenario
    if scenarioAllModels.shape[0] == 0:
        return False
    
    scenarioNo=scenarioAllModels[(scenarioAllModels)['model']==0]
    rsaNo=scenarioNo['RSA'].iloc[0]
    scenarioDouble=scenarioAllModels[(scenarioAllModels)['model']==1]
    rsaDouble=scenarioDouble['RSA'].iloc[0]
    scenarioData=scenarioAllModels[(scenarioAllModels)['model']==2]
    rsaData=scenarioData['RSA'].iloc[0]
    scenarioPoints=scenarioAllModels[(scenarioAllModels)['model']==3]
    rsaPoints=scenarioPoints['RSA'].iloc[0]
    scenarioFull=scenarioAllModels[(scenarioAllModels)['model']==4]
    rsaFull=scenarioFull['RSA'].iloc[0]
    
    models=[-1, 0, 1, 2, 3, 4]
    for model in models:
        scenarioBestPartition=df[(df['coreCount'] == coreCount) &
            (df['minTaskUtil'] == taskUtilRange[0]) &
            (df['maxTaskUtil'] == taskUtilRange[1]) &
            (df['numPeriods'] == numPeriods) &
            (df['expected_score'] == expected_score) &
            (df['score_distro'] == distro) &
            (df['slope'] == slope) &
            (df['model'] == model) &
            (df['bestPartition'] == True) ]
        
        rsa=scenarioBestPartition['RSA'].iloc[0]
        improvement=scenarioBestPartition['improvement'].iloc[0]
        
        rsaImpLabel=" (RSA=" + str("%.2f" % rsa) + ", RI=" + str("%.2f" % improvement) +")"
    
        if model == -1:
            modelName = "Baseline       (RSA=" + str("%.2f" % rsa) + ")"
            modelStyle = 'solid'
            modelColor = '#1b9e77'  # blue-green
        elif model == 0:
            modelName = "No Pre.        " + rsaImpLabel
            modelStyle = 'dotted'
            #modelColor = '#d95f02'  # dk orange
            modelColor='#7570b3'#purple
            #modelColor='#66161e'#yellow-green
        elif model == 1:
            continue
            # modelName="Double Cost" + rsaImpLabel
            # modelStyle="dashed"
            # modelColor='#7570b3'#purple
        elif model == 2:
            # modelName="Data Driven" + rsaImpLabel
            modelName = "Partial Pre.  " + rsaImpLabel
            modelStyle = "dashdot"
            modelColor = '#e7298a'  # hot pink
            #modelColor='#7570b3'#purple
        elif model == 3:
            continue
            # modelName="Pre. Points  " + rsaImpLabel
            # modelStyle=(0, (1, 1)) #densely dotted
            # modelColor='#66161e'#yellow-green
        elif model == 4:
            modelName = "Full Pre.       " + rsaImpLabel
            #modelStyle = (0, (3, 5, 1, 5, 1, 5))  # dashdotdotted
            modelStyle="dashed"
            modelColor = '#000000'  # black
        
        #get success rates for chosen scenario and partition
        successRates=[]
        j=0
        #print("model: ", model)
        while j * BIN_SIZE <= maxTotalUtil:
            if j <=LAST_BIN:
                columnName=str(j)
                successRates.append(scenarioBestPartition[columnName].iloc[0])
            else:
                successRates.append(0)
            j +=1
        
        #graph the success rates vs. utilization

        target.plot(util, successRates, label=modelName, linestyle=modelStyle, color=modelColor)
        target.set_title(writeHeader(coreCount, taskUtilRange[0], taskUtilRange[1],
                                     numPeriods, expected_score, slope, distro))
    target.set_ylim(0,1.02)
    target.set_xlim(minTotalUtil, maxTotalUtil)
    target.set_xlabel('Utilization')
    target.set_ylabel('Schedulability Ratio')
    target.legend()


def writeHeader(coreCount, minTaskUtil, maxTaskUtil, numPeriods, expected_score, slope, distro):
    #coreCount, Mij distrib
    #task Util, periodCount
    #
    coreHeader=str(str(coreCount) + " Cores")
    
    periodHeader=str(str(numPeriods) + " Periods")
    # SMT header should show expected, slope,
    smtHeader = "f(1): " + str(expected_score) + ", slope: " + str(slope)
    if distro == 0:
        smtHeader += ", fixed"
    elif distro == 1:
        smtHeader += ", expo"
    utilHeader="Task Util~U(" + str(minTaskUtil) + ", " + str(maxTaskUtil) + ")"
    fullHeader="\n" + coreHeader + ", " + utilHeader + ", " + periodHeader +"\n" + smtHeader
    
    return fullHeader


SPLIT_UNIFORM=1
SPLIT_NORMAL=2

FILE_IN="500SamplesProcessed.csv"
df=pd.read_csv(FILE_OUT)
FOLDER_OUT = "TestQuands/"

NUM_COLUMNS=df.shape[1]
LAST_BIN=NUM_COLUMNS-19

BIN_SIZE=.25

#DISTRIBUTIONS=[(SPLIT_UNIFORM, 0.1, 0.8, 0.1)]

EXPECTED = (0.35, 0.55, 0.75)
SLOPE = (0.0, 0.15, 0.30)
DISTRO = (0, 1)

TASK_UTIL_RANGES=[(0, .4), (.3, .7), (.6, 1), (0, 1)]

name=1
for coreCount in [4, 8, 16]:
    for numPeriods in [4, 8]:
        for expected_score in EXPECTED:
            for slope in SLOPE:
                for distro in DISTRO:
                    if distro == 0:
                        distro_string = "fixed"
                    elif distro == 1:
                        distro_string = "exponential"
                    #smt_string = "E[f(1)]: " + str(expected_score) + " slope: " + str(slope) + ", " + distro_string
                    fileName = str(coreCount) + "-" + str(numPeriods) + "-" + str(expected_score) + "-" + str(slope) + "-" + str(distro)
                    plotUtilQuad(coreCount, expected_score, slope, distro, numPeriods, fileName)
                    name+=1
        
    

